package com.gr.staffpm.datatypes;

import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;

import javax.persistence.Basic;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Transient;

import org.hibernate.annotations.Proxy;

/**
 * Hibernate mapping class for User Table
 * <p>Because this class performs its own Realm and Permission checks, and these can happen frequently enough in a
 * production application, it is highly recommended that the internal User {@link #getRoles} collection be cached
 * in a 2nd-level cache when using JPA and/or Hibernate.</p>
 * 
 * @author Graham Rhodes
 * @date   29 Oct 2010
 */
@Entity
@Proxy(lazy = false)
@Table(name = "users")
public class User implements Serializable {

    private static final long serialVersionUID = 1L;
    public static final String USERNAME = "username";
    public static final String EMAIL = "emailAddress";
    public static final String FIRST_NAME = "firstName";
    public static final String LAST_NAME = "lastName";
    public static final String FULL_NAME = "fullName";
    private int userId = 0;
    private String username = null;
    private String firstName = null;
    private String lastName = null;
    private String password = null;
    private String emailAddress = null;
    private Set<Group> groups = new HashSet<Group>();
    private boolean gcalEnabled = false;
    private String gcalAuth = "";
    private Set<Role> roles = new HashSet<Role>();
    private User createdBy = null;
    private Date created = new Date(Calendar.getInstance().getTimeInMillis());
    private User updatedBy = null;
    private Date lastUpdated = new Date(Calendar.getInstance().getTimeInMillis());

    public User() {
    }

    @Id
    @GeneratedValue
    @Column(name = "user_id")
    public int getUserId() {
        return userId;
    }

    @Basic
    @Column(name = "username")
    public String getUsername() {
        return username;
    }

    @Basic
    @Column(name = "first_name")
    public String getFirstName() {
        return firstName;
    }

    @Basic
    @Column(name = "last_name")
    public String getLastName() {
        return lastName;
    }

    @Transient
    public String getFullName() {
        return firstName + " " + lastName;
    }

    @Basic
    @Column(name = "password")
    public String getPassword() {
        return password;
    }

    @Basic
    @Column(name = "email_address")
    public String getEmailAddress() {
        return emailAddress;
    }

    @ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    @JoinTable(name = "users_groups", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "group_id"))
    public Set<Group> getGroups() {
        return groups;
    }

    @Basic
    @Column(name = "gcalEnabled")
    public boolean isGcalEnabled() {
        return gcalEnabled;
    }

    @Basic
    @Column(name = "gcalAuth")
    public String getGcalAuth() {
        return gcalAuth;
    }

    @OneToMany(fetch = FetchType.EAGER)
    @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id"))
    public Set<Role> getRoles() {
        return roles;
    }

    @ManyToOne
    @JoinColumn(name = "createdBy")
    public User getCreatedBy() {
        return createdBy;
    }

    @Column(name = "created")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getCreated() {
        return created;
    }

    @ManyToOne
    @JoinColumn(name = "updatedBy")
    public User getUpdatedBy() {
        return updatedBy;
    }

    @Column(name = "lastUpdated")
    @Temporal(TemporalType.TIMESTAMP)
    public Date getLastUpdated() {
        return lastUpdated;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public void setEmailAddress(String emailAddress) {
        this.emailAddress = emailAddress;
    }

    public void setGroups(Set<Group> groups) {
        this.groups = groups;
    }

    public void setGcalEnabled(boolean gcalEnabled) {
        this.gcalEnabled = gcalEnabled;
    }

    public void setGcalAuth(String gcalAuth) {
        this.gcalAuth = gcalAuth;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    public void setCreatedBy(User createdBy) {
        this.createdBy = createdBy;
    }

    public void setCreated(Date created) {
        this.created = created;
    }

    public void setUpdatedBy(User updatedBy) {
        this.updatedBy = updatedBy;
    }

    public void setLastUpdated(Date lastUpdated) {
        this.lastUpdated = lastUpdated;
    }

    @Override
    public boolean equals(Object obj) {
        User other = (User) obj;
        return this.username.equals(other.getUsername());
    }

}
